import tkinter as tk
from tkinter import ttk


def calculate_tolerance(unit_field_dec, unit_val_dec, total_field_dec, total_val_dec, unit_price, quantity):
    """计算价格容差和范围，返回容差、范围及预期总价"""
    try:
        unit_decimals = unit_val_dec if unit_val_dec != 0 else unit_field_dec
        total_decimals = total_val_dec if total_val_dec != 0 else total_field_dec

        epsilon_unit = abs(quantity) * 0.5 * (10 ** -unit_decimals)
        epsilon_total = 0.5 * (10 ** -total_decimals)
        total_tolerance = epsilon_unit + epsilon_total

        expected_total = round(unit_price * quantity,
                               total_decimals)  # 预期总价按总价字段小数位四舍五入‌:ml-citation{ref="1,4" data="citationList"}
        lower = expected_total - total_tolerance
        upper = expected_total + total_tolerance

        return (
            round(total_tolerance, max(unit_decimals, total_decimals)),
            round(lower, total_decimals),
            round(upper, total_decimals),
            expected_total
        )
    except:
        return (None, None, None, None)


def on_calculate():
    """计算按钮事件处理"""
    try:
        params = {k: float(v.get()) if k in ['unit_price', 'quantity', 'actual_total'] else int(v.get())
                  for k, v in entries.items()}

        tolerance, lower, upper, expected_total = calculate_tolerance(
            params['unit_field_dec'],
            params['unit_val_dec'],
            params['total_field_dec'],
            params['total_val_dec'],
            params['unit_price'],
            params['quantity']
        )

        actual = params['actual_total']
        difference = round(actual - expected_total,
                           params['total_field_dec'])  # 差值保持与总价相同精度‌:ml-citation{ref="1,2" data="citationList"}
        result = "Pass" if (lower <= actual <= upper) else "Fail"

        result_text.config(state='normal')
        result_text.delete(1.0, tk.END)
        result_text.insert(tk.END,
                           f"预期总价: {expected_total}\n"
                           
                           f"实际总价差值: {difference}\n"
                           
                           f"计算容差: {tolerance}\n"
                           
                           f"总价范围: [{lower}, {upper}]\n"
                           
                           f"实际总价: {actual} → {result}"
                           )
        result_text.config(state='disabled')
    except Exception as e:
        result_text.config(state='normal')
        result_text.delete(1.0, tk.END)
        result_text.insert(tk.END, f"输入错误: {str(e)}")
        result_text.config(state='disabled')


def clear_entries():
    """清空所有输入和结果"""
    for entry in entries.values():
        entry.delete(0, tk.END)
    result_text.config(state='normal')
    result_text.delete(1.0, tk.END)
    result_text.config(state='disabled')


# 界面布局
root = tk.Tk()
root.title("价格容差计算器 V2.0")
root.geometry("550x450")

mainframe = ttk.Frame(root, padding="20")
mainframe.grid(column=0, row=0, sticky=(tk.W, tk.E, tk.N, tk.S))

labels = {
    'unit_field_dec': "单价字段小数位",
    'unit_val_dec': "单价数值小数位",
    'total_field_dec': "总价字段小数位",
    'total_val_dec': "总价数值小数位",
    'unit_price': "单价数值",
    'quantity': "数量",
    'actual_total': "实际总价"
}

entries = {}
for i, (key, text) in enumerate(labels.items()):
    ttk.Label(mainframe, text=text + ": ").grid(column=0, row=i, sticky=tk.W)
    entries[key] = ttk.Entry(mainframe)
    entries[key].grid(column=1, row=i, sticky=tk.EW)

# 功能按钮
ttk.Button(mainframe, text="计算", command=on_calculate).grid(column=1, row=7, pady=10)
ttk.Button(mainframe, text="清空", command=clear_entries).grid(column=2, row=7, pady=10)

# 结果显示
result_text = tk.Text(mainframe, height=8, width=40, state='disabled')
result_text.grid(column=0, row=8, columnspan=3, pady=10)

root.mainloop()
